#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
阿里云Paraformer语音识别模块
基于HTTP API实现音频文件转文本功能
"""

import os
import json
import base64
import requests
from pathlib import Path
from config.config import Config

class SpeechRecognizer:
    def __init__(self, api_key=None, api_url=None):
        """
        初始化语音识别器
        
        Args:
            api_key (str): API Token，如果为None则从环境变量获取
            api_url (str): API URL，如果为None则从环境变量获取
        """
        self.api_key = api_key or os.getenv('SPEECH_API_TOKEN')
        self.api_url = api_url or os.getenv('SPEECH_API_URL')
        
        if not self.api_key:
            raise ValueError("请设置SPEECH_API_TOKEN环境变量或传入api_key参数")
        if not self.api_url:
            raise ValueError("请设置SPEECH_API_URL环境变量或传入api_url参数")
        
        # 默认配置
        self.format = 'wav'
        self.sample_rate = 16000
    def encode_file_to_base64(self, file_path):
        """
        将音频文件编码为base64格式 - 优化版本，避免内存溢出
        
        Args:
            file_path (str): 音频文件路径
            
        Returns:
            str: JSON格式的base64编码数据
        """
        # 更严格的文件大小检查
        file_size = os.path.getsize(file_path)
        max_size = 30 * 1024 * 1024  # 降低到30MB限制
        
        if file_size > max_size:
            raise Exception(f"文件过大: {file_size / (1024*1024):.1f}MB，超过30MB限制")
        
        print(f"[DEBUG] 编码音频文件: {file_path}, 大小: {file_size / 1024 / 1024:.2f}MB")
        
        try:
            # 一次性读取整个文件进行base64编码
            with open(file_path, "rb") as f:
                encoded_string = base64.b64encode(f.read()).decode('utf-8')
            
            # 检查编码后的大小
            encoded_size = len(encoded_string)
            print(f"[DEBUG] Base64编码后大小: {encoded_size / 1024 / 1024:.2f}MB")
            
            # Base64编码后大小检查（降低到40MB）
            base64_size_limit = 40 * 1024 * 1024  # 40MB限制
            # 如果编码后仍然过大，抛出异常
            if encoded_size > base64_size_limit:
                raise ValueError(f"Base64编码后文件过大 ({encoded_size / 1024 / 1024:.1f}MB)")
            
            data = json.dumps({"audio": encoded_string})
            return data
            
        except MemoryError:
            raise ValueError("文件过大，内存不足以完成编码")
        except Exception as e:
            raise ValueError(f"文件编码失败: {str(e)}")
        
    def recognize_file(self, audio_file_path, output_file=None):
        """
        识别音频文件并返回文本结果
        
        Args:
            audio_file_path (str): 音频文件路径
            output_file (str): 输出文件路径，如果为None则不保存文件
            
        Returns:
            dict: 包含识别结果的字典
        """
        try:
            # 检查文件是否存在
            if not os.path.exists(audio_file_path):
                raise FileNotFoundError(f"音频文件不存在: {audio_file_path}")
            
            print(f"开始识别音频文件: {audio_file_path}")
            
            # 直接使用原始文件，不进行任何转换
            audio_file_to_process = audio_file_path
            
            # 编码音频文件
            request_body = self.encode_file_to_base64(audio_file_to_process)
            
            # 设置请求头
            headers = {"Authorization": self.api_key, "Content-Type": "application/json"}
            
            # 发送HTTP请求
            # 根据文件大小动态设置超时时间
            file_size_mb = os.path.getsize(audio_file_to_process) / (1024 * 1024)
            timeout = max(60, int(file_size_mb * 2))  # 至少60秒，大文件按2秒/MB计算
            print(f"文件大小: {file_size_mb:.2f} MB，设置超时时间: {timeout} 秒")
            
            response = requests.post(url=self.api_url, headers=headers, data=request_body, timeout=timeout)
            
            print(f"API响应状态码: {response.status_code}")
            
            if response.status_code == 200:
                # 解析响应结果
                response_data = response.json()
                print(f"[DEBUG] API原始响应: {response_data}")
                
                # 提取识别文本（根据实际API响应格式调整）
                if 'text' in response_data:
                    full_text = response_data['text']
                    print(f"[DEBUG] 从response_data['text']提取文本: {full_text}")
                elif 'result' in response_data and 'text' in response_data['result']:
                    full_text = response_data['result']['text']
                    print(f"[DEBUG] 从response_data['result']['text']提取文本: {full_text}")
                elif isinstance(response_data, list) and len(response_data) > 0:
                    # 处理列表格式的响应
                    if isinstance(response_data[0], dict) and 'text' in response_data[0]:
                        full_text = response_data[0]['text']
                        print(f"[DEBUG] 从response_data[0]['text']提取文本: {full_text}")
                    else:
                        full_text = str(response_data)
                        print(f"[DEBUG] 列表格式但无text字段，转换为字符串: {full_text}")
                else:
                    # 如果响应格式不明确，尝试从整个响应中提取文本
                    full_text = str(response_data)
                    print(f"[DEBUG] 未知格式，转换为字符串: {full_text}")
                
                # 构建结果字典
                result_data = {
                    'status': 'success',
                    'text': full_text,
                    'audio_file': audio_file_path,
                    'raw_response': response_data
                }
                
                print(f"识别成功，文本长度: {len(full_text)} 字符")
                print(f"识别结果: {full_text[:100]}..." if len(full_text) > 100 else f"识别结果: {full_text}")
                
                # 保存结果到文件
                if output_file:
                    self.save_result(result_data, output_file)
                
                return result_data
                
            else:
                error_msg = f"API请求失败: 状态码 {response.status_code}, 响应: {response.text}"
                print(error_msg)
                return {
                    'status': 'error',
                    'error': error_msg,
                    'audio_file': audio_file_path
                }
                
        except Exception as e:
            error_msg = f"识别过程中发生异常: {str(e)}"
            print(error_msg)
            return {
                'status': 'error',
                'error': error_msg,
                'audio_file': audio_file_path
            }
    
    def save_result(self, result_data, output_file):
        """
        保存识别结果到文件
        
        Args:
            result_data (dict): 识别结果数据
            output_file (str): 输出文件路径
        """
        try:
            # 确保输出目录存在
            os.makedirs(os.path.dirname(output_file), exist_ok=True)
            
            # 保存为JSON格式
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(result_data, f, ensure_ascii=False, indent=2)
            
            print(f"识别结果已保存到: {output_file}")
            
        except Exception as e:
            print(f"保存结果失败: {str(e)}")
    
    def set_api_config(self, api_key=None, api_url=None):
        """
        设置API配置
        
        Args:
            api_key (str): API Token
            api_url (str): API URL
        """
        if api_key:
            self.api_key = api_key
        if api_url:
            self.api_url = api_url
        print(f"API配置已更新")

def test_recognition():
    """
    测试语音识别功能
    """
    try:
        # 从环境变量获取配置
        api_key = os.getenv('SPEECH_API_TOKEN')
        api_url = os.getenv('SPEECH_API_URL')
        
        if not api_key or not api_url:
            print("请先设置环境变量 SPEECH_API_TOKEN 和 SPEECH_API_URL")
            return
        
        # 创建识别器实例
        recognizer = SpeechRecognizer(api_key=api_key, api_url=api_url)
        
        # 测试音频文件路径（请替换为实际的音频文件）
        test_audio = "test_audio.wav"
        
        if os.path.exists(test_audio):
            print(f"测试识别音频文件: {test_audio}")
            result = recognizer.recognize_file(test_audio)
            
            if result['status'] == 'success':
                print(f"识别成功!")
                print(f"识别文本: {result['text']}")
            else:
                print(f"识别失败: {result['error']}")
        else:
            print(f"测试音频文件不存在: {test_audio}")
            print("请准备一个wav格式的音频文件进行测试")
            
    except Exception as e:
        print(f"测试过程中发生异常: {str(e)}")

if __name__ == "__main__":
    test_recognition()